#pragma once

#include "Thread.hpp"
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>

using namespace std;
using namespace ThreadModule;

const static int gdefaultthreadnum = 10;

template <typename T>
class ThreadPool
{
private:
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void P()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void V()
    {
        pthread_cond_signal(&_cond);
    }
    void ThreadWakeupAll()
    {
        pthread_cond_broadcast(&_cond);
    }

public:
    ThreadPool(int threadnum = gdefaultthreadnum)
        : _threadnum(threadnum), _waitnum(0), _isrunning(false)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    void InitThreadPool()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            string name = "thread-" + to_string(i + 1);
            _threads.emplace_back();
        }
    }

    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }

    void HandlerTask()
    {
        while (true)
        {
            // 1.队列是共享资源，加锁来保证共享资源互斥访问
            Lock();
            // 2.任务队列为空 -> 队列里没有数据  线程池还在运行
            while (_task_queue.empty() && _isrunning)
            {
                _waitnum++; // 等待的进程数量++
                P();        // 进程等待（wait）
                _waitnum--; // 等待结束，等待的进程数--
            }

            // 3.任务队列为空 且线程已经退出
            if (_task_queue.empty() && !_isrunning)
            {
                Unlock();
                break;
            }

            T t = _task_queue.front();
            _task_queue.pop();
            Unlock();
        }
    }

    void Stop()
    {
        Lock();
        _isrunning = false;
        ThreadWakeupAll();
        Unlock();
    }

    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
        }
    }

    bool Enqueue(T &in)
    {
        bool ret = false;
        Lock();
        if (_isrunning)
        {
            _task_queue.push(t);
            if (_waitnum > 0)
            {
                V();
            }
            ret = true;
        }
        Unlock();
        return ret;
    }

private:
    int _threadnum;          // 线程的数量
    vector<Thread> _threads; // 线程数组
    queue<T> _task_queue;    // 任务队列
    pthread_mutex_t _mutex;  // 互斥锁
    pthread_cond_t _cond;    // 信号量

    int _waitnum;
    bool _isrunning;
};